package com.dale.config;

import com.dale.shiro.AccountRealm;
import com.dale.shiro.JwtFilter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Autowired
    JwtFilter jwtFilter;

    /**
     * 改用DefaultSessionManager
     */
//    @Bean
//    public SessionManager sessionManager(RedisSessionDAO redisSessionDAO) {
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//
//        // inject redisSessionDAO
//        sessionManager.setSessionDAO(redisSessionDAO);
//        return sessionManager;
//    }

    /**
     * 使用原生的sessionManager
     * 参考：https://blog.csdn.net/u011456867/article/details/80484559
     *
     * @return
     */
    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        return sessionManager;
    }


    /**
     * 使用cacheManager
     * @return
     */
    @Bean
    public EhCacheManager cacheManager() {
        return new EhCacheManager();
    }



    @Bean
    public DefaultWebSecurityManager securityManager(AccountRealm accountRealm,
                                                     SessionManager sessionManager,
                                                     EhCacheManager ehCacheManager

    ) {
//                                                   ,RedisCacheManager redisCacheManager

        //开启缓存管理  分布式缓存
//        accountRealm.setCacheManager(new RedisCacheManager());
//        accountRealm.setCachingEnabled(true);//开启全局缓存
//        accountRealm.setAuthenticationCachingEnabled(true);//认证认证缓存
//        accountRealm.setAuthenticationCacheName("authenticationCache");
//        accountRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
//        accountRealm.setAuthorizationCacheName("authorizationCache");
        

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(accountRealm);

        //inject sessionManager
        securityManager.setSessionManager(sessionManager);

        // inject ehCacheManager
        securityManager.setCacheManager(ehCacheManager);
        accountRealm.setCachingEnabled(true);    //设置全局缓存
//        accountRealm.setAuthorizationCachingEnabled(true);  //开启授权缓存
//        accountRealm.setAuthenticationCachingEnabled(true); //开启认证缓存
        //设置完成


        //还可以分布式的采用redis缓存  注意+盐时 序列化  详情看编程不良人的

        //使用原生缓存
        //参考：https://blog.csdn.net/u014203449/article/details/79331417
//        securityManager.setCacheManager(new MemoryConstrainedCacheManager());

        return securityManager;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

//        Map<String, String> filterMap = new LinkedHashMap<>();
//
//        //顺序优先级判断哈
//        filterMap.put("/**", "jwt");
//
//        chainDefinition.addPathDefinitions(filterMap);
        return chainDefinition;
    }

    //往往将上一个配置  集合到下一个Bean中


    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager
//                                                         ShiroFilterChainDefinition shiroFilterChainDefinition
    ) {


        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
        filterMap.put("jwt", jwtFilter);
        shiroFilterFactoryBean.setFilters(filterMap);

        // <!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边

//        filterChainDefinitionMap.put("/blogs", "anon");  //表示blogs接口不会拦截验证
//        filterChainDefinitionMap.put("/logout", "anon");  //表示blogs接口不会拦截验证
//        filterChainDefinitionMap.put("/user/register", "anon");  //表示blogs接口不会拦截验证
//
//        filterChainDefinitionMap.put("/blog/edit", "jwt");
//        filterChainDefinitionMap.put("/user/editUser", "jwt");
//        filterChainDefinitionMap.put("/user/listUser", "jwt");
//        filterChainDefinitionMap.put("/user/changeUserStatue", "jwt");

        //关于authc
        /*
          我们也可以用这个过滤器做默认的登录逻辑，但是一般都是我们自己在控制器写登录逻辑的，自己写的话出错返回的信息都可以定制嘛。
        */
        //这几个不起作用
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/logout", "anon");
        filterChainDefinitionMap.put("/blogs", "anon");
        filterChainDefinitionMap.put("/register", "anon");
        filterChainDefinitionMap.put("/**", "jwt");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;


//        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
//        shiroFilter.setSecurityManager(securityManager);
//
//        Map<String, Filter> filters = new HashMap<>();
//        filters.put("jwt", jwtFilter);
//        shiroFilter.setFilters(filters);
//
//        // 添加自己的过滤器并且取名为jwt
//        Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
//        filterMap.put("jwt", new JwtFilter());
//        shiroFilter.setFilters(filterMap);
//        // <!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
//        filters.put("/**", "jwt");
//
//
//        Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap();
//
//        shiroFilter.setFilterChainDefinitionMap(filterMap);
//        return shiroFilter;
    }

}
